package jmine.tec.rpc.server.base;

import java.io.Serializable;

import jmine.tec.rpc.RPCMessages;
import jmine.tec.rpc.common.RPCException;
import jmine.tec.rpc.common.entity.EntityRepresentation;
import jmine.tec.rpc.server.representation.RepresentationFactory;
import bancosys.tec.persist.Persistable;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.persist.dao.BaseDAOFactory;
import bancosys.tec.persist.dao.BeanNotFoundException;

/**
 * Classe abstrata, base para implementações de serviços REST.
 * 
 * @author lundberg
 */
public abstract class AbstractRestServiceImplementor {

    private BaseDAOFactory daoFactory;

    private RepresentationFactory representationFactory;

    /**
     * @return the daoFactory
     */
    protected BaseDAOFactory getDAOFactory() {
        return this.daoFactory;
    }

    /**
     * @return the representationFactory
     */
    protected RepresentationFactory getRepresentationFactory() {
        return this.representationFactory;
    }

    /**
     * @param daoFactory the daoFactory to set
     */
    public void setDaoFactory(BaseDAOFactory daoFactory) {
        this.daoFactory = daoFactory;
    }

    /**
     * @param representationFactory the representationFactory to set
     */
    public void setRepresentationFactory(RepresentationFactory representationFactory) {
        this.representationFactory = representationFactory;
    }

    /**
     * Busca a entidade correspondente à representação dada
     * 
     * @param <S> tipo de representação
     * @param <T> tipo de entidade persistida
     * @param persistableClass persistableClass
     * @param representation representation
     * @return entity
     */
    protected <S extends EntityRepresentation, T extends Persistable> T findEntity(Class<T> persistableClass, S representation) {
        try {
            return this.findByPk(persistableClass, representation.getPk());
        } catch (BeanNotFoundException e) {
            throw new RPCException(RPCMessages.STALE_REPRESENTATION.create(representation.getPk()), e);
        }
    }

    /**
     * Busca a entidade do tipo e chave dados.
     * 
     * @param <T> tipo da entidade sendo buscada
     * @param persistableClass entityClass
     * @param pk pk
     * @return entidade
     * @throws BeanNotFoundException BeanNotFoundException
     */
    protected <T extends Persistable> T findByPk(Class<T> persistableClass, Serializable pk) throws BeanNotFoundException {
        BaseDAO<T> dao = this.getDAOFactory().getGenericDAO(persistableClass);
        return dao.findByPk(pk);
    }

    /**
     * Busca a entidade do tipo e chave natural dados.
     * 
     * @param <T> tipo da entidade sendo buscada
     * @param persistableClass entityClass
     * @param naturalKey naturalKey
     * @return entidade
     * @throws BeanNotFoundException BeanNotFoundException
     */
    protected <T extends Persistable> T findByNaturalKey(Class<T> persistableClass, Serializable naturalKey) throws BeanNotFoundException {
        BaseDAO<T> dao = this.getDAOFactory().getGenericDAO(persistableClass);
        return dao.findByNaturalKey(naturalKey);
    }
}
